package com.demister.at.util;

/**
 * Point represent the 2-dimension coordinate point. It contains x value and y value.X and y value can't be samller than 0.
 * @author Rock
 */
public class Point implements Comparable<Point> {

    private int x;
    private int y;

    private Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    /**
     * Return x value.
     * @return the x
     */
    public int getX() {
        return x;
    }

    /**
     * Return y value.
     * @return the y
     */
    public int getY() {
        return y;
    }

    public int compareTo(Point o) {
        if (this.getY() - o.getY() != 0) {
            return this.getY() - o.getY();
        } else {
            return this.getX() - o.getX();
        }
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return this;
    }

    @Override
    public String toString() {
        return String.format("(%d, %d)", this.getX(), this.getY());
    }
    private static Point[][] cache;

    /**
     * Initialize the point cache with specific x capacity and y capacity.
     * If cache exists, copy it to new cache.
     * @param xCapacity x capacity
     * @param yCapacity y capacity
     */
    public static void init(int xCapacity, int yCapacity) {
        Point[][] newCache = new Point[xCapacity][yCapacity];
        if (cache != null) {
            //copy exsiting point to new cache
            int bound1 = cache.length < newCache.length ? cache.length : newCache.length;
            int bound2 = cache[0].length < newCache[0].length ? cache[0].length : newCache[0].length;

            for (int i = 0; i < bound1; i++) {
                for (int j = 0; j < bound2; j++) {
                    newCache[i][j] = cache[i][j];
                }
            }
        }
        cache = newCache;
    }

    /**
     * Retuen the point object with specific x and y.
     * Such conditions should be satisfied,
     * <pre>
     *     0 <= x < xCapacity
     *     0 <= y < yCapacity
     *</pre>
     * otherwise exception is thrown.
     * @param x x
     * @param y y
     * @return
     */
    public static Point getPoint(int x, int y) {
        if (x < 0 || y <0 || x >= getXCapacity() || y >= getYCapacity())
            return new Point(x, y);
        if (cache[x][y] == null) {
            cache[x][y] = new Point(x, y);
        }
        return cache[x][y];
    }

    /**
     * Return the x capacity.
     * @return x capacity
     */
    public static int getXCapacity() {
        return cache == null ? -1 : cache.length;
    }

    /**
     * Return the y capacity
     * @return y capacity
     */
    public static int getYCapacity() {
        return cache == null ? -1 : cache[0].length;
    }
}
